/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package simulation2;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 *
 * @author kb191394
 */
public class EnginJeu {
   
    private Dice dice;

    public EnginJeu(Dice dice) {
        this.dice = dice;
    }
        
    /**
     * Initialise un tournois, demande le nom des joueurs au clavier.
     * @return 
     */
    public Tournois nouveauTournois(boolean fakeNoms) {
        
        ConsoleJeu.greeting();
        
        Tournois tournois = new Tournois();
        Partie partieInitiale = new Partie(TypePartie.INITIALE);
       
        if (!fakeNoms) {
            ConsoleJeu.lirePoule(partieInitiale.getPoule(0));
            ConsoleJeu.lirePoule(partieInitiale.getPoule(1));
        } else {
            partieInitiale.getPoule(0).ajouterJoueur(new Joueur("Arthur"));
            partieInitiale.getPoule(0).ajouterJoueur(new Joueur("Leodagan"));
            partieInitiale.getPoule(0).ajouterJoueur(new Joueur("Lancelot"));
            partieInitiale.getPoule(0).ajouterJoueur(new Joueur("Merlin"));
            
            partieInitiale.getPoule(1).ajouterJoueur(new Joueur("Ali"));
            partieInitiale.getPoule(1).ajouterJoueur(new Joueur("Cedric"));
            partieInitiale.getPoule(1).ajouterJoueur(new Joueur("Neilson"));
            partieInitiale.getPoule(1).ajouterJoueur(new Joueur("Imad"));
        }
        
        tournois.setPartieInitiale(partieInitiale);
        
        return tournois;
        
    }
    
    
    public List<List<Joueur>> jouerPartie(Partie partie) {
        
        List<List<Joueur>> gagnants = new ArrayList<List<Joueur>>();
        
        for(Poule poule : partie.getPoules()) {
            if (poule.isEmpty())
                continue;
            gagnants.add(jouerPartiePoule(poule, partie));
        }
        
        return gagnants;
        
    }
    
    /**
     * Retourne les gagnants
     * @param poule
     * @param partie
     * @return 
     */
    public List<Joueur> jouerPartiePoule(Poule poule, Partie partie) {
        
        System.out.println("===================================");
        System.out.println("Partie " + partie.getType());
        System.out.println("Poule " + poule.getNomPoule());
        
        int nbreGagnants = 1;
        if (partie.getType().equals(TypePartie.INITIALE))
            nbreGagnants = 2;
        
        List<Joueur> gagnants = jouerTour(poule.getListJoueurs(), partie, false, nbreGagnants, 0);
        
        System.out.println("Gagnants: ");
        for (Joueur joueur : gagnants) {
            System.out.println(joueur.getNom() + " (" + joueur.nombreVictoires(partie) + " victoires, " + joueur.getValeur() + " valeur)");
        }
        
        System.out.println("===================================");
        
        
        return gagnants;
    }
    
    public List<Joueur> jouerTour(List<Joueur> joueurs, Partie partie, boolean eliminatoire, int nbreGagnants, int niveauElim) {
        
        if (eliminatoire) {
            System.out.println(spacer(niveauElim) + "ELIMINATOIRES ENTRE:");
            System.out.print(spacer(niveauElim));
            for (Joueur joueur : joueurs) {
                System.out.print(joueur.getNom() + " ");
            }
            System.out.println("");
        }
        
        List<Joueur> copieListe = new ArrayList<Joueur>(joueurs);
        
        for (Joueur joueurA : joueurs) {
            
            joueurA.incNombreToursJoue();
            
            for (Joueur joueurB : copieListe) {
                if (joueurA == joueurB)
                    continue;

                if (joueurA.isEliminated() || joueurB.isEliminated())
                    continue;

                System.out.print(spacer(niveauElim));
                jouerTour(joueurA, joueurB, partie);

            }
            
            copieListe.remove(joueurA);
        }
        
        // Trouver 2 joueurs gagnants
        Map<Integer, List<Joueur>> resultats = classerResultats(joueurs, partie);
        
        List<Joueur> gagnants = new ArrayList<Joueur>();
        int gagnantsRestants = nbreGagnants;
        
        for (Integer points : resultats.keySet()) {
            List<Joueur> groupe = resultats.get(points);
           
            if (groupe.size() > gagnantsRestants ) {
                // TODO: ELIMINATOIRES ENTRE CES JOUEURS
                List<Joueur> gagnantsEleminatoire = jouerTour(groupe, partie, true, gagnantsRestants, niveauElim+1);
                gagnants.addAll(gagnantsEleminatoire);
                gagnantsRestants -= gagnantsEleminatoire.size();
                
                
            } else if (groupe.size() <= gagnantsRestants) {
                gagnants.addAll(groupe);
                gagnantsRestants -= groupe.size();
                
            }
            
            if (gagnantsRestants == 0)
                break;
            
        }
        
        
        return gagnants;
        
    }
    
    private SortedMap<Integer, List<Joueur>> classerResultats(List<Joueur> joueurs, Partie partie) {
        
        SortedMap<Integer, List<Joueur>> map = new TreeMap<Integer, List<Joueur>>();
        
        for (Joueur joueur : joueurs) {
           
            int points = joueur.getPoints(partie) * -1;
            
            List<Joueur> joueursPoints =  map.get(points);
            if (joueursPoints == null) {
                joueursPoints = new ArrayList<Joueur>();
                map.put(points, joueursPoints);
            }
            
            joueursPoints.add(joueur);
            
        }
        
        return map;
        
    } 
    
    
    /**
     * Joue le tour et retourne le joueur gagnant (null si aucun)
     * @param j1
     * @param j2
     * @return 
     */
    public void jouerTour(Joueur j1, Joueur j2, Partie partie) {
        
        System.out.print(j1 + " VS " + j2 + " : ");
        
        int[] resultat1 = lancerDes();
        System.out.print(" VS ");
        int[] resultat2 = lancerDes();
        
        int valeur1 = interpreterResultatLancementDes(resultat1);
        int valeur2 = interpreterResultatLancementDes(resultat2);
        
        j1.incValeur(valeur1);
        j2.incValeur(valeur2);
        
        if (valeur1 > 0) {
            j1.ajouterVictoire(partie);
            System.out.print(" Victoire " + j1.getNom());
        }
        
        if (valeur2 > 0) {
            j2.ajouterVictoire(partie);
            System.out.print(" Victoire " + j2.getNom());
        }
        
        System.out.print("\n");
        
    }
    
    public int interpreterResultatLancementDes(int[] resultats) {
        int total =  resultats[0] + resultats[1] + resultats[2]; 
        if( total < 8  || ( resultats[0]== 1 || resultats[1]== 2 )
                       || ( resultats[0]== 1 || resultats[2]== 2 )
                       || ( resultats[1]== 1 || resultats[2]== 2 ) 
                       || (total == 14)                          )
        {
            return 1;
        }
        else     
        {
            return -1;
        }
    }
    
    private int[] lancerDes() {
        int[] resultats = new int[3];
        resultats[0] = dice.throwDice();
        resultats[1] = dice.throwDice();
        resultats[2] = dice.throwDice();
        
        System.out.print(resultats[0] + "-" + resultats[1] + "-" + resultats[2]);
        
        return resultats;
    }    
    
    public void CompilerStat( List<Partie> partie )
    {
        Map<Integer,Joueur> MeilleurJouerurValue = getMeilleurJouerurValue(partie);
        Map<Integer,Joueur> MoinsJouerurTours = getMoinsToursJouerur(partie);
        Map<Integer,Joueur> MeilleurJouerurSirop = getMeilleurJouerurSirop(partie);
        
        System.out.println(" \nStatistiques : ");
        System.out.println("Joueur(s) avec plus de valeurs dans le match");
        
        Iterator iterValue = MeilleurJouerurValue.entrySet().iterator();
        while( iterValue.hasNext() )
        {
            Map.Entry valueJ =  (Map.Entry)iterValue.next();
            Joueur j = (Joueur)valueJ.getValue();
            System.out.println("joueur :"+j.getNom()+"   Nombre de valeurs :" +valueJ.getKey());
        }
        
        Iterator iterT = MoinsJouerurTours.entrySet().iterator();
        System.out.println("Joueur(s) avec moins de tours dans le match");
        while( iterT.hasNext() )
        {
            Map.Entry valueJ =  (Map.Entry)iterT.next();
            Joueur j = (Joueur)valueJ.getValue();
            System.out.println("joueur :"+j.getNom()+"   Nombre de tours :" +valueJ.getKey());
        }
        
        Iterator iterS = MeilleurJouerurSirop.entrySet().iterator();
        System.out.println("Joueur(s) avec plus de sirops dans le match");
        while( iterS.hasNext() )
        {
            Map.Entry valueJ =  (Map.Entry)iterS.next();
            Joueur j = (Joueur)valueJ.getValue();
            System.out.println("joueur :"+j.getNom()+"   Nombre de sirops :" +valueJ.getKey());
        }
    }
    
    public Map<Integer,Joueur> getMeilleurJouerurValue( List<Partie> parties )
    {
         Map<Integer,Joueur> statMeilleurValue = new HashMap<Integer,Joueur>();
         int maxValeur = 0;
         Joueur joueurMaxValeur = null;
         for(Partie partie : parties )
         {
            for(Poule poule : partie.getPoules()) 
            {
               for (Joueur joueur : poule.getListJoueurs()) 
               {
                   int valeur = joueur.getValeur();
                   if(valeur > maxValeur )
                   {
                       maxValeur = valeur;
                       joueurMaxValeur = joueur;
                       statMeilleurValue.clear();
                       statMeilleurValue.put(maxValeur, joueurMaxValeur);
                   }
                   else if( valeur == maxValeur )
                   {
                       statMeilleurValue.put(maxValeur, joueurMaxValeur);
                   }
               }
            }
         }
         
         return statMeilleurValue;
    }
    
    public Map<Integer,Joueur> getMoinsToursJouerur( List<Partie> parties )
    {
         Map<Integer,Joueur> statMoinsTours = new HashMap<Integer,Joueur>();
        
          int minTours = Integer.MAX_VALUE;
         Joueur joueurMinTours = null;
         for(Partie partie : parties )
         {
           for(Poule poule : partie.getPoules()) 
           {
               for (Joueur joueur : poule.getListJoueurs()) 
               {
                   int minToursJ = joueur.getNombreToursJoue();
                   if( minToursJ < minTours )
                   {
                       minTours = minToursJ;
                       joueurMinTours =  joueur;
                       
                       statMoinsTours.clear();
                       statMoinsTours.put( minToursJ, joueurMinTours );
                   }
                   else if( minTours == minToursJ )
                   {
                       statMoinsTours.put( minTours, joueurMinTours );
                   }
               }
           }
         }
        return statMoinsTours;
    }

    
    public Map<Integer,Joueur> getMeilleurJouerurSirop( List<Partie> parties )
    {
         Map<Integer,Joueur> statMeilleurSirop = new HashMap<Integer,Joueur>();
        
         int maxVictoires = 0;
         Joueur joueurMaxVictoires = null;
         
         for(Partie partie : parties )
         {
           for(Poule poule : partie.getPoules()) 
           {
               for (Joueur joueur : poule.getListJoueurs()) 
               {
                   int totalVictoires = joueur.getTotalVictoires();
                   if( totalVictoires > maxVictoires )
                   {
                       maxVictoires = totalVictoires;
                       joueurMaxVictoires =  joueur;
                       statMeilleurSirop.clear();
                       statMeilleurSirop.put(maxVictoires, joueurMaxVictoires);
                   }
                   else if( totalVictoires == maxVictoires )
                   {
                       statMeilleurSirop.put(maxVictoires, joueurMaxVictoires);
                   }
               }
            }
         }
         
        return statMeilleurSirop;
    }
    

    
    private String spacer(int nbre) {
        String str = "";
        for (int i = 0; i < nbre*4; i++) {
            str += " ";
        }
        return str;
    }
    
}
